﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Caca.MineSweeper
{
    public class MineFieldGenerator
    {
        public static char CHAR_Mine = 'X';
        public static char CHAR_NonMine = 'O';

        public static MineField Generate(string[] stringField)
        {
            return GenerateField(GenerateIntField(stringField), stringField[0].Length, stringField.Length);
        }

        public static MineField Generate(int width, int height, int totalMines)
        {
            var intField = GenerateIntField(width, height, totalMines);
            var result = GenerateField(intField, width, height);
            return result;
        }

        public static int[] GenerateIntField(string[] stringField)
        {
            int width = stringField[0].Length;
            int height = stringField.Length;

            int[] fields = new int[width * height];
            for (var h = 0; h < height; h++)
                for (var w = 0; w < width; w++)
                {
                    var c = stringField[h].ToUpper()[w];

                    if (c == CHAR_Mine)
                    {
                        //X 代表地雷,  将周围的非地雷格计数+1
                        AddSurroundCount(width, height, fields, w, h);
                        fields[w + width * h] = -1;     // -1 代表地雷格
                    }
                    else if (c == CHAR_NonMine)
                    {
                    }
                }

            return fields;
        }

        private static MineField GenerateField(int[] fields, int width, int height)
        {
            //int width = stringField[0].Length;
            //int height = stringField.Length;

            //int[] fields = GenerateIntField(stringField);

            List<Plot> plots = new List<Plot>(width * height);
            foreach (var f in fields)
            {
                if (f >= 0)
                {
                    plots.Add(new NonMinePlot(f));
                }
                else
                {
                    plots.Add(new MinePlot());
                }
            }

            return new MineField(width, height, plots);
        }

        private static int[] GenerateIntField(int width, int height, int totalMines)
        {
            int length = width * height;
            int[] fields = new int[length];

            int plantedMines = 0;
            Random r = new Random((int)DateTime.Now.Ticks);
            while (plantedMines < totalMines)
            {
                var index = r.Next(length);

                if (fields[index] == -1)
                    continue;

                fields[index] = -1;

                int x = index % width, y = index / width;

                AddSurroundCount(width, height, fields, x, y);
                plantedMines++;

            }

            return fields;
        }

        /// <summary>
        /// 在一个矩阵中, 将围绕指定座标, 周围的8个方格中的值+1, 注意, 不会增加超出矩阵边界的方格值.
        /// 座标原点为矩阵左上角顶点, 为0,0
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="fields">一维矩阵数据</param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private static void AddSurroundCount(int width, int height, int[] fields, int x, int y)
        {
            int[,] surround = new int[8, 2]{
                                {x-1,y-1},
                                {x, y-1},
                                {x+1, y-1},
                                {x-1, y},
                                {x+1, y},
                                {x-1, y+1},
                                {x, y+1},
                                {x+1, y+1}
                            };

            for (int i = 0; i < 8; i++)
            {
                var tempx = surround[i, 0];
                var tempy = surround[i, 1];
                if (tempx >= 0 && tempy >= 0 && tempx < width && tempy < height)    //边界判断
                    if (fields[tempx + width * tempy] >= 0)                     //是否是地雷格判断, 地雷格是-1
                        fields[tempx + width * tempy]++;
            }
        }

    }
}
